﻿using UnityEngine;

namespace Core
{
    public class AudioObject : Entity, IGameObject, IAwake, IUpdate
    {
        public GameObject gameObject { get; private set; }

        public Transform transform { get; private set; }
        public bool IsPlaying { get; private set; }
        public bool IsComplete { get; private set; }

        public float LastUseTime;

        private AudioSource source;

        private string resKey;
        private string resPath;
        private readonly char[] symbols = { '/', '.', '\\' };

        private double startTime;
        private float duration;

        public void SetRes(string res)
        {
            if (res.IndexOfAny(symbols) >= 0)
            {
                resKey = string.Empty;
                resPath = res;
            }
            else
            {
                resKey = res;
                resPath = string.Empty;
            }
        }

        public void Awake()
        {
            gameObject = new GameObject($"AudioObj_{InstanceId}");
            transform = gameObject.transform;

            transform.SetParent(G.Audio);
            transform.Reset();

            source = gameObject.AddComponent<AudioSource>();

            IsPlaying = false;
            IsComplete = false;
        }

        public override void Dispose()
        {
            if (IsDisposed) return;

            base.Dispose();
        }

        public float Volume
        {
            get => source.volume;
            set => source.volume = value;
        }

        private float mTime;

        public float Time
        {
            get => mTime;
            set
            {
                mTime = value;
                //log.err($"time = {value}");
            }
        }

        public float Pitch
        {
            get => source.pitch;
            set => source.pitch = value;
        }

        public void Start()
        {
            IsPlaying = true;
            IsComplete = false;
            startTime = AudioSettings.dspTime;
            duration = 1;
            //log.err($"Start resKey={resKey} InstanceId={InstanceId}");

            Load().Coroutine();
        }

        public void Stop()
        {
            if (IsDisposed) return;

            IsPlaying = false;
            IsComplete = true;
            source?.Stop();

            Volume = 1;
            Time = 0;
            Pitch = 1;
            //log.err($"stop 111 time={source.time}");
        }

        public void Update()
        {
            if (IsPlaying == false || IsComplete)
            {
                return;
            }

            if (AudioSettings.dspTime - startTime > duration)
            {
                IsComplete = true;
                source.Stop();
                //log.err($"stop 222 time={source.time}");
            }
        }

        private async ETTask Load()
        {
            Res.IAsset asset = null;
            if (string.IsNullOrEmpty(resKey) == false)
            {
                var conf = G.Table.GetSO<TblAudio>().Find(resKey);
                asset = await G.Res.LoadAsync(conf.ResPath);
            }

            if (string.IsNullOrEmpty(resPath) == false)
            {
                asset = await G.Res.LoadAsync(resPath);
            }

            if (IsPlaying == false)
            {
                return;
            }

            startTime = AudioSettings.dspTime;
            duration = 0;

            if (asset != null)
            {
                var clip = asset.Obj as AudioClip;
                if (clip == null) return;

                source.clip = clip;
                source.time = mTime;
                source.Play();
                //log.err($"play name={clip.name} m_time={m_time} time={source.time}");

                duration = clip.length - mTime;
            }
        }
    }
}
